<?php
class Bliss_Rcon_Protocol_Frostbite extends Bliss_Rcon_Protocol_Abstract
{
	public function encode($command, $args)
	{
		$packet = $this->encodePacket(false, false, $this->sequence, $command, $args);
		$this->sequence++;
		return $packet;
	}

	protected function encodePacket($isFromServer, $isResponse, $sequence, $command, $args)
	{
		$args  = isset($args) ? $args : array();
		$words = array_merge(array($command), $args);
		$encodedHeader = $this->encodeHeader($isFromServer, $isResponse, $sequence);
		$encodedNumWords = $this->encodeInt32(count($words));
		list($wordsSize, $encodedWords) = $this->encodeWords($words);
		$encodedSize = $this->encodeInt32($wordsSize + 12);
		return $encodedHeader . $encodedSize . $encodedNumWords . $encodedWords;
	}

	protected function encodeHeader($isFromServer, $isResponse, $sequence)
	{
		$header = $sequence & 0x3fffffff;
		if ($isFromServer)
			$header += 0x80000000;
		if ($isResponse)
			$header += 0x40000000;

		// Not tested this bit

		return pack('I', $header);
	}

	protected function encodeWords($words)
	{
		$size = 0;
		$encodedWords = '';
		foreach($words as $word) {
			$strWord = $word;
			$encodedWords .= $this->encodeInt32(strlen($strWord));
			$encodedWords .= $strWord;
			$encodedWords .= "\x00";
			$size += strlen($strWord) + 5;
		}
		return array($size, $encodedWords);
	}

	public function decode($data)
	{
		list($isFromServer, $isResponse, $sequence) = $this->decodeHeader($data);
		$wordsSize = $this->decodeInt32(substr($data,4,4)) - 12;
		$words = $this->decodeWords($wordsSize, substr($data,12));
		return array($isFromServer, $isResponse, $sequence, $words);
	}

	protected function decodeHeader($data)
	{
		$header = unpack('I', $data);
		return array($header & 0x80000000, $header & 0x40000000, $header & 0x3fffffff);
	}

	protected function decodeWords($size, $data)
	{
		$numWords = $this->decodeInt32($data);
		$offset = 0;
		while ($offset < $size)
		{
			$wordLen = $this->decodeInt32(substr($data,$offset,4));
			$word = substr($data,$offset+4,$wordLen);
			$words[] = $word;
			$offset += $wordLen + 5;
		}

		return $words;
	}
}
?>